Skip to content

Conversation

@nflaig
Copy link
Member

@nflaig nflaig commented Dec 4, 2025

Motivation

Closes #8606

Description

This updates our implementation to be compliant with latest spec ethereum/beacon-APIs#368.

For sync committee aggregation selection (unchanged)

  • we call submitSyncCommitteeSelections at the start of the slot
  • the timeout is still based on CONTRIBUTION_DUE_BPS into the slot (8 seconds)
  • we call the endpoint for all duties for this slot
  • logic has been moved to duties service

For attestation aggregation selection

  • we call submitBeaconCommitteeSelections at the start of the epoch for current and next epoch (2 separate calls)
  • the timeout uses default which is based on SLOT_DURATION_MS (12 seconds)
  • we only call prepareBeaconCommitteeSubnet once the above call either resolved or fails, this should fine as it's not that time sensitive (one epoch lookahead)
  • if duties are reorged, we will call submitBeaconCommitteeSelections with duties of affected epoch
  • logic has been moved to duties service

Previous PR #5344

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @nflaig, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the handling of beacon and sync committee selections for distributed validator clients. The core change involves shifting the submission of selection proofs from a per-slot operation within the AttestationService and SyncCommitteeService to a more efficient, less frequent execution within their respective *DutiesService counterparts. This optimization aims to reduce redundant operations by processing selections once per epoch for beacon committees and once per slot during duty calculation for sync committees, thereby streamlining the validator client's interaction with the distributed validator middleware.

Highlights

  • Beacon Committee Selection Frequency: The submission of beacon committee selections for distributed validator clients has been optimized to occur once per epoch, rather than per slot, by moving the logic from AttestationService to AttestationDutiesService.
  • Sync Committee Selection Frequency: Similarly, sync committee selection submissions are now handled once per slot within the duty calculation process in SyncCommitteeDutiesService, instead of per slot in SyncCommitteeService.
  • API Documentation Updates: The API documentation for validator endpoints (submitBeaconCommitteeSelections and submitSyncCommitteeSelections) has been updated to reflect the new recommended querying frequencies for distributed validator clients.
  • Code Refactoring: The runDistributedAggregationSelectionTasks method, responsible for exchanging partial for combined selection proofs and determining aggregators, has been refactored and moved to the respective *DutiesService classes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the submission of beacon committee selections to occur once per epoch, rather than per slot. This is achieved by relocating the runDistributedAggregationSelectionTasks logic from AttestationService to AttestationDutiesService. A similar refactoring has been applied to sync committee duties, moving logic from SyncCommitteeService to SyncCommitteeDutiesService. The changes are logical and align with the goal of reducing submission frequency.

I have one suggestion to improve the robustness of the new implementation in attestationDuties.ts.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

Performance Report

🚀🚀 Significant benchmark improvement detected

Benchmark suite Current: d09182f Previous: 1f2a3a4 Ratio
500 bytes - compress - snappy 1.3826 us/op 6.3037 us/op 0.22
300 bytes - uncompress - snappyjs 962.29 ns/op 20.794 us/op 0.05
send data - 1000 16384B messages 102.26 ms/op 579.21 ms/op 0.18
send data - 1000 65536B messages 299.40 ms/op 1.9022 s/op 0.16
Full columns - reconstruct half of the blobs out of 6 138.84 us/op 15.718 ms/op 0.01
Full benchmark results
Benchmark suite Current: d09182f Previous: 1f2a3a4 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 1.1046 ms/op 1.2700 ms/op 0.87
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 36.882 us/op 39.826 us/op 0.93
BLS verify - blst 818.20 us/op 803.94 us/op 1.02
BLS verifyMultipleSignatures 3 - blst 1.1691 ms/op 1.4913 ms/op 0.78
BLS verifyMultipleSignatures 8 - blst 1.6623 ms/op 1.7086 ms/op 0.97
BLS verifyMultipleSignatures 32 - blst 4.9041 ms/op 7.4935 ms/op 0.65
BLS verifyMultipleSignatures 64 - blst 9.5567 ms/op 9.8610 ms/op 0.97
BLS verifyMultipleSignatures 128 - blst 21.520 ms/op 18.589 ms/op 1.16
BLS deserializing 10000 signatures 711.37 ms/op 732.72 ms/op 0.97
BLS deserializing 100000 signatures 6.8757 s/op 7.2788 s/op 0.94
BLS verifyMultipleSignatures - same message - 3 - blst 813.93 us/op 1.0232 ms/op 0.80
BLS verifyMultipleSignatures - same message - 8 - blst 999.31 us/op 1.1759 ms/op 0.85
BLS verifyMultipleSignatures - same message - 32 - blst 1.6535 ms/op 1.9188 ms/op 0.86
BLS verifyMultipleSignatures - same message - 64 - blst 2.5663 ms/op 2.8479 ms/op 0.90
BLS verifyMultipleSignatures - same message - 128 - blst 4.4082 ms/op 4.6297 ms/op 0.95
BLS aggregatePubkeys 32 - blst 19.349 us/op 20.199 us/op 0.96
BLS aggregatePubkeys 128 - blst 69.073 us/op 72.589 us/op 0.95
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 45.878 ms/op 54.316 ms/op 0.84
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 37.338 ms/op 44.596 ms/op 0.84
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 31.031 ms/op 36.819 ms/op 0.84
getSlashingsAndExits - default max 70.956 us/op 83.587 us/op 0.85
getSlashingsAndExits - 2k 318.53 us/op 367.93 us/op 0.87
isKnown best case - 1 super set check 196.00 ns/op 214.00 ns/op 0.92
isKnown normal case - 2 super set checks 193.00 ns/op 215.00 ns/op 0.90
isKnown worse case - 16 super set checks 188.00 ns/op 216.00 ns/op 0.87
InMemoryCheckpointStateCache - add get delete 2.2810 us/op 2.4540 us/op 0.93
validate api signedAggregateAndProof - struct 1.3354 ms/op 1.4635 ms/op 0.91
validate gossip signedAggregateAndProof - struct 1.3529 ms/op 1.4863 ms/op 0.91
batch validate gossip attestation - vc 640000 - chunk 32 113.44 us/op 123.04 us/op 0.92
batch validate gossip attestation - vc 640000 - chunk 64 99.953 us/op 105.52 us/op 0.95
batch validate gossip attestation - vc 640000 - chunk 128 94.399 us/op 101.35 us/op 0.93
batch validate gossip attestation - vc 640000 - chunk 256 89.795 us/op 100.95 us/op 0.89
pickEth1Vote - no votes 925.87 us/op 1.1923 ms/op 0.78
pickEth1Vote - max votes 5.6198 ms/op 6.2318 ms/op 0.90
pickEth1Vote - Eth1Data hashTreeRoot value x2048 10.220 ms/op 13.642 ms/op 0.75
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 13.453 ms/op 15.431 ms/op 0.87
pickEth1Vote - Eth1Data fastSerialize value x2048 376.44 us/op 405.85 us/op 0.93
pickEth1Vote - Eth1Data fastSerialize tree x2048 3.3856 ms/op 3.0066 ms/op 1.13
bytes32 toHexString 342.00 ns/op 367.00 ns/op 0.93
bytes32 Buffer.toString(hex) 234.00 ns/op 301.00 ns/op 0.78
bytes32 Buffer.toString(hex) from Uint8Array 307.00 ns/op 578.00 ns/op 0.53
bytes32 Buffer.toString(hex) + 0x 229.00 ns/op 524.00 ns/op 0.44
Object access 1 prop 0.11300 ns/op 0.31700 ns/op 0.36
Map access 1 prop 0.11500 ns/op 0.13900 ns/op 0.83
Object get x1000 5.1910 ns/op 8.1560 ns/op 0.64
Map get x1000 0.37600 ns/op 0.69200 ns/op 0.54
Object set x1000 28.456 ns/op 50.328 ns/op 0.57
Map set x1000 19.838 ns/op 42.936 ns/op 0.46
Return object 10000 times 0.23040 ns/op 0.32930 ns/op 0.70
Throw Error 10000 times 3.9266 us/op 8.5678 us/op 0.46
toHex 142.49 ns/op 306.72 ns/op 0.46
Buffer.from 119.43 ns/op 220.50 ns/op 0.54
shared Buffer 78.145 ns/op 131.02 ns/op 0.60
fastMsgIdFn sha256 / 200 bytes 1.8030 us/op 3.2040 us/op 0.56
fastMsgIdFn h32 xxhash / 200 bytes 191.00 ns/op 471.00 ns/op 0.41
fastMsgIdFn h64 xxhash / 200 bytes 256.00 ns/op 619.00 ns/op 0.41
fastMsgIdFn sha256 / 1000 bytes 5.8510 us/op 11.495 us/op 0.51
fastMsgIdFn h32 xxhash / 1000 bytes 286.00 ns/op 567.00 ns/op 0.50
fastMsgIdFn h64 xxhash / 1000 bytes 320.00 ns/op 686.00 ns/op 0.47
fastMsgIdFn sha256 / 10000 bytes 52.114 us/op 87.456 us/op 0.60
fastMsgIdFn h32 xxhash / 10000 bytes 1.4010 us/op 2.0080 us/op 0.70
fastMsgIdFn h64 xxhash / 10000 bytes 939.00 ns/op 1.5100 us/op 0.62
100 bytes - compress - snappyjs 1.2049 us/op 2.7623 us/op 0.44
100 bytes - compress - snappy 1.1833 us/op 2.8761 us/op 0.41
200 bytes - compress - snappyjs 1.5385 us/op 3.6812 us/op 0.42
200 bytes - compress - snappy 1.3037 us/op 2.3119 us/op 0.56
300 bytes - compress - snappyjs 1.8351 us/op 2.6340 us/op 0.70
300 bytes - compress - snappy 1.4488 us/op 2.6745 us/op 0.54
400 bytes - compress - snappyjs 2.2293 us/op 3.7737 us/op 0.59
400 bytes - compress - snappy 1.4521 us/op 2.9394 us/op 0.49
500 bytes - compress - snappyjs 2.3714 us/op 5.1656 us/op 0.46
500 bytes - compress - snappy 1.3826 us/op 6.3037 us/op 0.22
1000 bytes - compress - snappyjs 4.4017 us/op 7.9987 us/op 0.55
1000 bytes - compress - snappy 1.5403 us/op 3.6855 us/op 0.42
10000 bytes - compress - snappyjs 26.210 us/op 37.359 us/op 0.70
10000 bytes - compress - snappy 24.940 us/op 13.372 us/op 1.87
100 bytes - uncompress - snappyjs 916.59 ns/op 1.4218 us/op 0.64
100 bytes - uncompress - snappy 1.1508 us/op 2.2186 us/op 0.52
200 bytes - uncompress - snappyjs 1.2608 us/op 2.1465 us/op 0.59
200 bytes - uncompress - snappy 1.2595 us/op 2.3365 us/op 0.54
300 bytes - uncompress - snappyjs 962.29 ns/op 20.794 us/op 0.05
300 bytes - uncompress - snappy 1.1436 us/op 2.2084 us/op 0.52
400 bytes - uncompress - snappyjs 1.0943 us/op 1.5932 us/op 0.69
400 bytes - uncompress - snappy 1.2609 us/op 1.9386 us/op 0.65
500 bytes - uncompress - snappyjs 1.3624 us/op 2.8382 us/op 0.48
500 bytes - uncompress - snappy 2.1977 us/op 2.1332 us/op 1.03
1000 bytes - uncompress - snappyjs 2.2908 us/op 2.7542 us/op 0.83
1000 bytes - uncompress - snappy 1.5885 us/op 2.9723 us/op 0.53
10000 bytes - uncompress - snappyjs 22.361 us/op 20.833 us/op 1.07
10000 bytes - uncompress - snappy 30.109 us/op 13.066 us/op 2.30
send data - 1000 256B messages 16.105 ms/op 21.687 ms/op 0.74
send data - 1000 512B messages 16.251 ms/op 40.249 ms/op 0.40
send data - 1000 1024B messages 23.602 ms/op 61.018 ms/op 0.39
send data - 1000 1200B messages 26.534 ms/op 50.130 ms/op 0.53
send data - 1000 2048B messages 28.440 ms/op 54.160 ms/op 0.53
send data - 1000 4096B messages 55.186 ms/op 60.553 ms/op 0.91
send data - 1000 16384B messages 102.26 ms/op 579.21 ms/op 0.18
send data - 1000 65536B messages 299.40 ms/op 1.9022 s/op 0.16
enrSubnets - fastDeserialize 64 bits 867.00 ns/op 2.1600 us/op 0.40
enrSubnets - ssz BitVector 64 bits 336.00 ns/op 816.00 ns/op 0.41
enrSubnets - fastDeserialize 4 bits 130.00 ns/op 197.00 ns/op 0.66
enrSubnets - ssz BitVector 4 bits 337.00 ns/op 367.00 ns/op 0.92
prioritizePeers score -10:0 att 32-0.1 sync 2-0 235.38 us/op 335.96 us/op 0.70
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 266.71 us/op 710.52 us/op 0.38
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 394.36 us/op 562.80 us/op 0.70
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 735.72 us/op 1.5084 ms/op 0.49
prioritizePeers score 0:0 att 64-1 sync 4-1 893.83 us/op 1.3239 ms/op 0.68
array of 16000 items push then shift 1.5703 us/op 1.9884 us/op 0.79
LinkedList of 16000 items push then shift 7.2560 ns/op 13.421 ns/op 0.54
array of 16000 items push then pop 73.792 ns/op 115.01 ns/op 0.64
LinkedList of 16000 items push then pop 6.9370 ns/op 15.171 ns/op 0.46
array of 24000 items push then shift 2.3331 us/op 3.7900 us/op 0.62
LinkedList of 24000 items push then shift 7.5330 ns/op 20.450 ns/op 0.37
array of 24000 items push then pop 104.12 ns/op 161.35 ns/op 0.65
LinkedList of 24000 items push then pop 7.0870 ns/op 12.136 ns/op 0.58
intersect bitArray bitLen 8 5.6630 ns/op 9.7930 ns/op 0.58
intersect array and set length 8 33.093 ns/op 60.181 ns/op 0.55
intersect bitArray bitLen 128 25.464 ns/op 44.139 ns/op 0.58
intersect array and set length 128 544.92 ns/op 1.0555 us/op 0.52
bitArray.getTrueBitIndexes() bitLen 128 1.0100 us/op 1.6730 us/op 0.60
bitArray.getTrueBitIndexes() bitLen 248 1.7650 us/op 2.5260 us/op 0.70
bitArray.getTrueBitIndexes() bitLen 512 3.6440 us/op 5.3730 us/op 0.68
Full columns - reconstruct all 6 blobs 326.62 us/op 379.50 us/op 0.86
Full columns - reconstruct half of the blobs out of 6 138.84 us/op 15.718 ms/op 0.01
Full columns - reconstruct single blob out of 6 43.552 us/op 54.882 us/op 0.79
Half columns - reconstruct all 6 blobs 262.31 ms/op 399.69 ms/op 0.66
Half columns - reconstruct half of the blobs out of 6 130.72 ms/op 207.20 ms/op 0.63
Half columns - reconstruct single blob out of 6 48.628 ms/op 76.913 ms/op 0.63
Full columns - reconstruct all 10 blobs 350.65 us/op 484.47 us/op 0.72
Full columns - reconstruct half of the blobs out of 10 152.66 us/op 258.97 us/op 0.59
Full columns - reconstruct single blob out of 10 29.781 us/op 48.862 us/op 0.61
Half columns - reconstruct all 10 blobs 440.53 ms/op 680.33 ms/op 0.65
Half columns - reconstruct half of the blobs out of 10 222.68 ms/op 335.16 ms/op 0.66
Half columns - reconstruct single blob out of 10 49.881 ms/op 78.713 ms/op 0.63
Full columns - reconstruct all 20 blobs 774.95 us/op 887.94 us/op 0.87
Full columns - reconstruct half of the blobs out of 20 328.38 us/op 475.16 us/op 0.69
Full columns - reconstruct single blob out of 20 37.341 us/op 60.278 us/op 0.62
Half columns - reconstruct all 20 blobs 917.91 ms/op 1.2699 s/op 0.72
Half columns - reconstruct half of the blobs out of 20 447.05 ms/op 576.07 ms/op 0.78
Half columns - reconstruct single blob out of 20 48.494 ms/op 58.554 ms/op 0.83
Set add up to 64 items then delete first 2.4548 us/op 3.0623 us/op 0.80
OrderedSet add up to 64 items then delete first 3.4267 us/op 3.9247 us/op 0.87
Set add up to 64 items then delete last 2.5466 us/op 3.2395 us/op 0.79
OrderedSet add up to 64 items then delete last 3.9359 us/op 5.3551 us/op 0.73
Set add up to 64 items then delete middle 2.6706 us/op 2.7663 us/op 0.97
OrderedSet add up to 64 items then delete middle 5.6921 us/op 5.7092 us/op 1.00
Set add up to 128 items then delete first 5.0214 us/op 5.2125 us/op 0.96
OrderedSet add up to 128 items then delete first 7.3180 us/op 7.6030 us/op 0.96
Set add up to 128 items then delete last 4.8847 us/op 5.5227 us/op 0.88
OrderedSet add up to 128 items then delete last 7.3191 us/op 8.8988 us/op 0.82
Set add up to 128 items then delete middle 4.7392 us/op 5.2616 us/op 0.90
OrderedSet add up to 128 items then delete middle 15.200 us/op 15.600 us/op 0.97
Set add up to 256 items then delete first 9.8755 us/op 15.903 us/op 0.62
OrderedSet add up to 256 items then delete first 14.796 us/op 20.208 us/op 0.73
Set add up to 256 items then delete last 9.7274 us/op 11.941 us/op 0.81
OrderedSet add up to 256 items then delete last 14.717 us/op 18.349 us/op 0.80
Set add up to 256 items then delete middle 9.7162 us/op 11.427 us/op 0.85
OrderedSet add up to 256 items then delete middle 42.321 us/op 47.162 us/op 0.90
pass gossip attestations to forkchoice per slot 2.5299 ms/op 2.7405 ms/op 0.92
forkChoice updateHead vc 100000 bc 64 eq 0 476.13 us/op 529.46 us/op 0.90
forkChoice updateHead vc 600000 bc 64 eq 0 2.8054 ms/op 3.2640 ms/op 0.86
forkChoice updateHead vc 1000000 bc 64 eq 0 4.6965 ms/op 5.7619 ms/op 0.82
forkChoice updateHead vc 600000 bc 320 eq 0 2.8825 ms/op 3.1446 ms/op 0.92
forkChoice updateHead vc 600000 bc 1200 eq 0 2.8994 ms/op 3.3211 ms/op 0.87
forkChoice updateHead vc 600000 bc 7200 eq 0 3.2010 ms/op 4.5212 ms/op 0.71
forkChoice updateHead vc 600000 bc 64 eq 1000 3.4150 ms/op 4.3179 ms/op 0.79
forkChoice updateHead vc 600000 bc 64 eq 10000 3.5173 ms/op 3.8656 ms/op 0.91
forkChoice updateHead vc 600000 bc 64 eq 300000 8.7128 ms/op 11.423 ms/op 0.76
computeDeltas 1400000 validators 0% inactive 14.534 ms/op 18.805 ms/op 0.77
computeDeltas 1400000 validators 10% inactive 13.654 ms/op 15.000 ms/op 0.91
computeDeltas 1400000 validators 20% inactive 12.971 ms/op 13.710 ms/op 0.95
computeDeltas 1400000 validators 50% inactive 9.8464 ms/op 10.717 ms/op 0.92
computeDeltas 2100000 validators 0% inactive 21.665 ms/op 23.876 ms/op 0.91
computeDeltas 2100000 validators 10% inactive 20.841 ms/op 22.332 ms/op 0.93
computeDeltas 2100000 validators 20% inactive 19.210 ms/op 21.512 ms/op 0.89
computeDeltas 2100000 validators 50% inactive 14.899 ms/op 16.106 ms/op 0.93
altair processAttestation - 250000 vs - 7PWei normalcase 2.0012 ms/op 2.8526 ms/op 0.70
altair processAttestation - 250000 vs - 7PWei worstcase 2.7666 ms/op 3.6356 ms/op 0.76
altair processAttestation - setStatus - 1/6 committees join 114.84 us/op 130.24 us/op 0.88
altair processAttestation - setStatus - 1/3 committees join 228.21 us/op 244.07 us/op 0.94
altair processAttestation - setStatus - 1/2 committees join 318.27 us/op 343.48 us/op 0.93
altair processAttestation - setStatus - 2/3 committees join 411.73 us/op 438.32 us/op 0.94
altair processAttestation - setStatus - 4/5 committees join 565.35 us/op 608.65 us/op 0.93
altair processAttestation - setStatus - 100% committees join 664.51 us/op 733.02 us/op 0.91
altair processBlock - 250000 vs - 7PWei normalcase 3.9966 ms/op 4.0893 ms/op 0.98
altair processBlock - 250000 vs - 7PWei normalcase hashState 16.320 ms/op 22.087 ms/op 0.74
altair processBlock - 250000 vs - 7PWei worstcase 23.993 ms/op 26.605 ms/op 0.90
altair processBlock - 250000 vs - 7PWei worstcase hashState 53.758 ms/op 66.737 ms/op 0.81
phase0 processBlock - 250000 vs - 7PWei normalcase 1.5340 ms/op 1.6647 ms/op 0.92
phase0 processBlock - 250000 vs - 7PWei worstcase 19.567 ms/op 21.558 ms/op 0.91
altair processEth1Data - 250000 vs - 7PWei normalcase 374.75 us/op 406.88 us/op 0.92
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 7.6730 us/op 8.2860 us/op 0.93
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 50.816 us/op 50.719 us/op 1.00
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 12.985 us/op 12.963 us/op 1.00
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 7.0590 us/op 8.1990 us/op 0.86
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 179.36 us/op 206.27 us/op 0.87
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.9173 ms/op 1.9480 ms/op 0.98
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 2.4963 ms/op 2.5923 ms/op 0.96
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 2.4999 ms/op 3.0696 ms/op 0.81
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 4.8629 ms/op 6.0693 ms/op 0.80
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.6278 ms/op 2.6305 ms/op 1.00
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 4.8688 ms/op 5.5790 ms/op 0.87
Tree 40 250000 create 368.01 ms/op 411.40 ms/op 0.89
Tree 40 250000 get(125000) 124.68 ns/op 132.91 ns/op 0.94
Tree 40 250000 set(125000) 1.2415 us/op 1.4392 us/op 0.86
Tree 40 250000 toArray() 15.823 ms/op 28.808 ms/op 0.55
Tree 40 250000 iterate all - toArray() + loop 13.794 ms/op 18.880 ms/op 0.73
Tree 40 250000 iterate all - get(i) 43.511 ms/op 54.397 ms/op 0.80
Array 250000 create 2.5646 ms/op 2.8224 ms/op 0.91
Array 250000 clone - spread 821.73 us/op 938.10 us/op 0.88
Array 250000 get(125000) 0.34700 ns/op 0.37600 ns/op 0.92
Array 250000 set(125000) 0.35200 ns/op 0.39100 ns/op 0.90
Array 250000 iterate all - loop 62.044 us/op 68.405 us/op 0.91
phase0 afterProcessEpoch - 250000 vs - 7PWei 41.943 ms/op 44.682 ms/op 0.94
Array.fill - length 1000000 2.8337 ms/op 3.1783 ms/op 0.89
Array push - length 1000000 9.9823 ms/op 14.574 ms/op 0.68
Array.get 0.22574 ns/op 0.22986 ns/op 0.98
Uint8Array.get 0.22700 ns/op 0.23688 ns/op 0.96
phase0 beforeProcessEpoch - 250000 vs - 7PWei 14.378 ms/op 15.262 ms/op 0.94
altair processEpoch - mainnet_e81889 225.10 ms/op 323.22 ms/op 0.70
mainnet_e81889 - altair beforeProcessEpoch 18.608 ms/op 23.011 ms/op 0.81
mainnet_e81889 - altair processJustificationAndFinalization 5.3890 us/op 6.2100 us/op 0.87
mainnet_e81889 - altair processInactivityUpdates 3.9337 ms/op 4.0907 ms/op 0.96
mainnet_e81889 - altair processRewardsAndPenalties 17.672 ms/op 22.035 ms/op 0.80
mainnet_e81889 - altair processRegistryUpdates 647.00 ns/op 760.00 ns/op 0.85
mainnet_e81889 - altair processSlashings 173.00 ns/op 228.00 ns/op 0.76
mainnet_e81889 - altair processEth1DataReset 166.00 ns/op 170.00 ns/op 0.98
mainnet_e81889 - altair processEffectiveBalanceUpdates 4.3294 ms/op 9.3723 ms/op 0.46
mainnet_e81889 - altair processSlashingsReset 841.00 ns/op 978.00 ns/op 0.86
mainnet_e81889 - altair processRandaoMixesReset 1.1080 us/op 1.1420 us/op 0.97
mainnet_e81889 - altair processHistoricalRootsUpdate 167.00 ns/op 170.00 ns/op 0.98
mainnet_e81889 - altair processParticipationFlagUpdates 508.00 ns/op 667.00 ns/op 0.76
mainnet_e81889 - altair processSyncCommitteeUpdates 132.00 ns/op 182.00 ns/op 0.73
mainnet_e81889 - altair afterProcessEpoch 45.214 ms/op 47.623 ms/op 0.95
capella processEpoch - mainnet_e217614 736.05 ms/op 974.62 ms/op 0.76
mainnet_e217614 - capella beforeProcessEpoch 67.270 ms/op 70.033 ms/op 0.96
mainnet_e217614 - capella processJustificationAndFinalization 5.6430 us/op 6.7050 us/op 0.84
mainnet_e217614 - capella processInactivityUpdates 18.471 ms/op 22.073 ms/op 0.84
mainnet_e217614 - capella processRewardsAndPenalties 102.30 ms/op 119.18 ms/op 0.86
mainnet_e217614 - capella processRegistryUpdates 6.4170 us/op 6.7050 us/op 0.96
mainnet_e217614 - capella processSlashings 176.00 ns/op 183.00 ns/op 0.96
mainnet_e217614 - capella processEth1DataReset 166.00 ns/op 306.00 ns/op 0.54
mainnet_e217614 - capella processEffectiveBalanceUpdates 27.170 ms/op 19.437 ms/op 1.40
mainnet_e217614 - capella processSlashingsReset 828.00 ns/op 889.00 ns/op 0.93
mainnet_e217614 - capella processRandaoMixesReset 1.1330 us/op 1.2100 us/op 0.94
mainnet_e217614 - capella processHistoricalRootsUpdate 175.00 ns/op 182.00 ns/op 0.96
mainnet_e217614 - capella processParticipationFlagUpdates 540.00 ns/op 552.00 ns/op 0.98
mainnet_e217614 - capella afterProcessEpoch 122.56 ms/op 121.72 ms/op 1.01
phase0 processEpoch - mainnet_e58758 253.30 ms/op 277.64 ms/op 0.91
mainnet_e58758 - phase0 beforeProcessEpoch 49.719 ms/op 61.573 ms/op 0.81
mainnet_e58758 - phase0 processJustificationAndFinalization 5.6410 us/op 5.8820 us/op 0.96
mainnet_e58758 - phase0 processRewardsAndPenalties 18.555 ms/op 18.717 ms/op 0.99
mainnet_e58758 - phase0 processRegistryUpdates 3.0960 us/op 3.2220 us/op 0.96
mainnet_e58758 - phase0 processSlashings 168.00 ns/op 175.00 ns/op 0.96
mainnet_e58758 - phase0 processEth1DataReset 169.00 ns/op 168.00 ns/op 1.01
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.1182 ms/op 992.32 us/op 1.13
mainnet_e58758 - phase0 processSlashingsReset 885.00 ns/op 995.00 ns/op 0.89
mainnet_e58758 - phase0 processRandaoMixesReset 1.1210 us/op 1.1130 us/op 1.01
mainnet_e58758 - phase0 processHistoricalRootsUpdate 166.00 ns/op 175.00 ns/op 0.95
mainnet_e58758 - phase0 processParticipationRecordUpdates 918.00 ns/op 962.00 ns/op 0.95
mainnet_e58758 - phase0 afterProcessEpoch 35.909 ms/op 38.162 ms/op 0.94
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.9134 ms/op 1.3812 ms/op 1.39
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 3.2688 ms/op 2.1463 ms/op 1.52
altair processInactivityUpdates - 250000 normalcase 14.708 ms/op 16.558 ms/op 0.89
altair processInactivityUpdates - 250000 worstcase 14.451 ms/op 18.340 ms/op 0.79
phase0 processRegistryUpdates - 250000 normalcase 5.9480 us/op 5.3660 us/op 1.11
phase0 processRegistryUpdates - 250000 badcase_full_deposits 297.81 us/op 281.05 us/op 1.06
phase0 processRegistryUpdates - 250000 worstcase 0.5 75.798 ms/op 88.866 ms/op 0.85
altair processRewardsAndPenalties - 250000 normalcase 17.875 ms/op 20.464 ms/op 0.87
altair processRewardsAndPenalties - 250000 worstcase 17.149 ms/op 18.719 ms/op 0.92
phase0 getAttestationDeltas - 250000 normalcase 17.212 ms/op 16.833 ms/op 1.02
phase0 getAttestationDeltas - 250000 worstcase 6.9891 ms/op 12.029 ms/op 0.58
phase0 processSlashings - 250000 worstcase 106.14 us/op 154.18 us/op 0.69
altair processSyncCommitteeUpdates - 250000 11.318 ms/op 14.469 ms/op 0.78
BeaconState.hashTreeRoot - No change 196.00 ns/op 234.00 ns/op 0.84
BeaconState.hashTreeRoot - 1 full validator 86.874 us/op 92.283 us/op 0.94
BeaconState.hashTreeRoot - 32 full validator 1.4347 ms/op 1.4903 ms/op 0.96
BeaconState.hashTreeRoot - 512 full validator 9.0306 ms/op 9.0500 ms/op 1.00
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 123.66 us/op 123.82 us/op 1.00
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 2.2071 ms/op 1.7060 ms/op 1.29
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 19.583 ms/op 18.212 ms/op 1.08
BeaconState.hashTreeRoot - 1 balances 90.328 us/op 82.530 us/op 1.09
BeaconState.hashTreeRoot - 32 balances 934.98 us/op 1.0151 ms/op 0.92
BeaconState.hashTreeRoot - 512 balances 7.4717 ms/op 7.6918 ms/op 0.97
BeaconState.hashTreeRoot - 250000 balances 124.51 ms/op 187.68 ms/op 0.66
aggregationBits - 2048 els - zipIndexesInBitList 21.470 us/op 22.275 us/op 0.96
regular array get 100000 times 25.018 us/op 26.026 us/op 0.96
wrappedArray get 100000 times 25.090 us/op 26.022 us/op 0.96
arrayWithProxy get 100000 times 14.372 ms/op 13.554 ms/op 1.06
ssz.Root.equals 24.379 ns/op 24.478 ns/op 1.00
byteArrayEquals 23.658 ns/op 23.794 ns/op 0.99
Buffer.compare 10.142 ns/op 10.238 ns/op 0.99
processSlot - 1 slots 12.012 us/op 11.962 us/op 1.00
processSlot - 32 slots 2.1590 ms/op 2.7929 ms/op 0.77
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 4.6660 ms/op 4.4269 ms/op 1.05
getCommitteeAssignments - req 1 vs - 250000 vc 1.9252 ms/op 1.9984 ms/op 0.96
getCommitteeAssignments - req 100 vs - 250000 vc 3.7643 ms/op 3.8370 ms/op 0.98
getCommitteeAssignments - req 1000 vs - 250000 vc 4.0210 ms/op 4.1241 ms/op 0.97
findModifiedValidators - 10000 modified validators 529.69 ms/op 470.46 ms/op 1.13
findModifiedValidators - 1000 modified validators 408.15 ms/op 443.12 ms/op 0.92
findModifiedValidators - 100 modified validators 289.52 ms/op 333.74 ms/op 0.87
findModifiedValidators - 10 modified validators 154.17 ms/op 197.17 ms/op 0.78
findModifiedValidators - 1 modified validators 149.64 ms/op 209.08 ms/op 0.72
findModifiedValidators - no difference 161.83 ms/op 202.84 ms/op 0.80
migrate state 1500000 validators, 3400 modified, 2000 new 1.0913 s/op 1.2313 s/op 0.89
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.4600 ns/op 4.4300 ns/op 1.01
state getBlockRootAtSlot - 250000 vs - 7PWei 557.76 ns/op 551.70 ns/op 1.01
computeProposerIndex 100000 validators 1.5721 ms/op 1.5967 ms/op 0.98
getNextSyncCommitteeIndices 1000 validators 119.95 ms/op 125.59 ms/op 0.96
getNextSyncCommitteeIndices 10000 validators 118.79 ms/op 125.66 ms/op 0.95
getNextSyncCommitteeIndices 100000 validators 118.72 ms/op 127.03 ms/op 0.93
computeProposers - vc 250000 658.73 us/op 841.38 us/op 0.78
computeEpochShuffling - vc 250000 77.933 ms/op 43.695 ms/op 1.78
getNextSyncCommittee - vc 250000 10.570 ms/op 11.069 ms/op 0.95
nodejs block root to RootHex using toHex 138.74 ns/op 150.03 ns/op 0.92
nodejs block root to RootHex using toRootHex 88.653 ns/op 93.611 ns/op 0.95
nodejs fromHex(blob) 365.14 us/op 256.07 us/op 1.43
nodejs fromHexInto(blob) 711.43 us/op 722.17 us/op 0.99
nodejs block root to RootHex using the deprecated toHexString 569.16 ns/op 595.48 ns/op 0.96
browser block root to RootHex using toHex 275.61 ns/op 312.70 ns/op 0.88
browser block root to RootHex using toRootHex 154.58 ns/op 158.23 ns/op 0.98
browser fromHex(blob) 1.1755 ms/op 1.3890 ms/op 0.85
browser fromHexInto(blob) 686.39 us/op 732.46 us/op 0.94
browser block root to RootHex using the deprecated toHexString 365.26 ns/op 420.29 ns/op 0.87

by benchmarkbot/action


this.logger.debug("Submitting partial beacon committee selection proofs", {epoch, count: partialSelections.length});

const res = await this.api.validator.submitBeaconCommitteeSelections({selections: partialSelections});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we call this with duties for a whole epoch, could consider batching the request but generally assume vc and charon run on the same host without any proxy in-between that could cause issues due to large request body size

* 3. Mutate duty objects to set selection proofs for aggregators
* 4. Resubscribe validators as aggregators on beacon committee subnets
*
* See https://docs.google.com/document/d/1q9jOTPcYQa-3L8luRvQJ-M0eegtba4Nmon3dpO79TMk/mobilebasic
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the google doc is no longer accessible

@nflaig nflaig marked this pull request as ready for review December 4, 2025 21:45
@nflaig nflaig requested a review from a team as a code owner December 4, 2025 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update vc to submit beacon committee selections once per epoch

2 participants